SPB Git forge
15commits 1branches 0releases
29.7 MBsize
maindefault branch
10 days agolast push
TypeScript 36.3% Python 31.8% Go 18% JavaScript 9.8% Shell 1.9% SQL 1.4% CSS 0.5%
4.6 KB · 99 lines tsx
Raw Blame History
1import type { Metadata } from 'next';2import Link from 'next/link';3import { ComponentGrid } from '@/components/detail/ComponentGrid';4import { ScopeHeader } from '@/components/detail/ScopeHeader';5import { ScopePressureChart } from '@/components/detail/ScopeCharts';6import { LatencyMatrixTable, LinkList, ProbesTable } from '@/components/detail/Tables';7import { IncidentsSection } from '@/components/incidents/IncidentsSection';8import { Section, Stat } from '@/components/ui/primitives';9import { apiGet, apiTry } from '@/lib/api';10import { fmt, fmtDelta, fmtInt, fmtPct } from '@/lib/format';11import type { RegionDetailResponse } from '@/lib/types';1213export const dynamic = 'force-dynamic';1415type Params = Promise<{ region: string }>;1617export async function generateMetadata({ params }: { params: Params }): Promise<Metadata> {18  const { region } = await params;19  const r = await apiTry<RegionDetailResponse>(`/api/v1/pressure/region/${encodeURIComponent(region)}`);20  if (!r) return { title: 'Region' };21  return { title: `${r.name} — Internet pressure ${fmt(r.pressure)} (${r.level_label})`, description: `Live Internet pressure for ${r.name}: ${fmt(r.pressure)} ${r.level_label}, ${fmtDelta(r.delta_1h)} over 1 h. ${r.probes.length} probes, ${r.targets} anchored targets.`, alternates: { canonical: `/internet/${region}` } };22}2324export default async function RegionPage({ params }: { params: Params }) {25  const { region } = await params;26  const r = await apiGet<RegionDetailResponse>(`/api/v1/pressure/region/${encodeURIComponent(region)}`);27  const last24 = r.history_24h.points;28  const first = last24[0]?.pressure;29  const change24 = first != null ? r.pressure - first : null;30  return (31    <div className="pb-8">32      <ScopeHeader33        kicker={`Region · ${r.continent}`}34        title={r.name}35        subtitle={36          <>37            Source view from {r.probes.length} probe{r.probes.length === 1 ? '' : 's'} blended with the destination view toward {fmtInt(r.targets)} anchored targets · role {r.role}38            {!r.coverage_ok && <span className="text-warn"> · weak coverage — conclusions damped</span>}39          </>40        }41        pressure={r.pressure}42        level={r.level}43        delta1h={r.delta_1h}44        trend={r.trend}45        confidence={r.confidence}46        meta={47          <>48            <span>49              Δ24h <span className="text-ink">{fmtDelta(change24)}</span>50            </span>51            <span>52              7d median <span className="text-ink">{fmt(r.baseline_7d.median)}</span> · p90 <span className="text-ink">{fmt(r.baseline_7d.p90)}</span>53            </span>54            <span>55              centroid <span className="text-ink">{r.lat}, {r.lon}</span>56            </span>57          </>58        }59      />6061      <Section label="Components">62        <ComponentGrid components={r.components} />63        {r.components.routing == null && <p className="mt-2 text-[11.5px] text-ink-3">Routing is not attributable to this region (no ASN attribution) — shown as n/a, not zero.</p>}64      </Section>6566      <Section label="24 h" right={<span>vs 7-day baseline</span>}>67        <ScopePressureChart series={r.history_24h} baseline={r.baseline_7d} height={240} />68      </Section>6970      <div className="grid grid-cols-[minmax(0,1fr)] gap-x-10 lg:grid-cols-2">71        <Section label="Top ASNs" className="min-w-0">72          <LinkList items={r.top_asns.map((a) => ({ key: String(a.asn), name: a.name, pressure: a.pressure, sub: `AS${a.asn}` }))} hrefFor={(k) => `/asn/${k}`} label="ASNs" />73        </Section>74        <Section label="Services observed" className="min-w-0">75          <LinkList items={r.top_services.map((s) => ({ key: s.slug, name: s.name, pressure: s.pressure, sub: `avail ${fmtPct(s.observed_availability_24h, 2)}` }))} hrefFor={(k) => `/service/${k}`} label="services" />76        </Section>77      </div>7879      <Section label="Latency matrix" right={<span>pairs from/to this region · z vs baseline</span>}>80        <LatencyMatrixTable rows={r.matrix} highlight={r.id} />81      </Section>8283      <Section label="Incidents" right={<Link href="/incidents" className="hover:text-ink">all incidents →</Link>}>84        <IncidentsSection incidents={r.incidents} />85      </Section>8687      <Section label="Probe coverage">88        <div className="mb-3 grid grid-cols-3 gap-4 sm:grid-cols-4">89          <Stat label="probes" value={fmtInt(r.probes.length)} />90          <Stat label="targets" value={fmtInt(r.targets)} />91          <Stat label="confidence" value={`${Math.round(r.confidence * 100)} %`} />92          <Stat label="coverage" value={r.coverage_ok ? 'ok' : 'weak'} />93        </div>94        <ProbesTable probes={r.probes} compact />95      </Section>96    </div>97  );98}99